package com.zdxf.controller;

import com.alibaba.fastjson.JSONObject;
import com.zdxf.compoent.WebSocketServer;
import com.zdxf.conf.Constant;
import com.zdxf.domain.CsvDO;
import com.zdxf.domain.SystemInfoDO;
import com.zdxf.domain.UserDO;
import com.zdxf.domain.XmlDO;
import com.zdxf.service.impl.TestServiceImpl;
import com.zdxf.util.CsvUtil;
import com.zdxf.util.Result;
import com.zdxf.util.XmlUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.hardware.NetworkIF;
import oshi.util.FormatUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

@Api(tags = "测试接口")
@RestController
@RequestMapping("/test")
public class TestController {
    @Autowired
    TestServiceImpl loginService;

    Result result = Constant.RESULT_EMPTY;

    @ApiOperation(value = "post接口测试", notes = "post接口测试")
    @ResponseBody()
    @PostMapping(value = "/post")
    public Object selectTouristGenderList(@RequestBody UserDO body, HttpServletResponse response) throws Exception {
        HashMap<String, Object> params = new HashMap<>(Constant.HASH_MAP_SIZE);
        params.put("username", body.getUsername());
        params.put("password", body.getPassword());
        result = loginService.login(params);
        return result.getData();
    }

//    @ApiOperation(value = "get接口测试", notes = "get接口测试")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "type", value = "类型（day、month、quarter、year）", required = true, paramType = "query"),
//    })
//    @GetMapping(value = "/get")
//    public Object selectTownshipUploadList(HttpServletRequest request, HttpServletResponse response) throws Exception {
//        HashMap<String, Object> params = new HashMap<>(Constant.HASH_MAP_SIZE);
//        params.put("type", request.getParameter("type"));
//        result = loginService.getList(params);
//        WebSocketServer.sendInfo(JSONObject.toJSONString(result.getData()));
//        return result.getData();
//    }

    @ApiOperation(value = "启动组件", notes = "启动组件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "", required = true, paramType = "query"),
    })
    @GetMapping(value = "/start")
    public Object start(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HashMap<String, Object> params = new HashMap<>(Constant.HASH_MAP_SIZE);

        params.put("type", request.getParameter("type"));
        String[] command;
        if (params.get("type").equals("yarn")) {
            command = new String[]{"/root/hadoop-2.7.2/sbin/start-yarn.sh"};
        } else if (params.get("type").equals("hdfs")) {
            command = new String[]{"/root/hadoop-2.7.2/sbin/start-dfs.sh"};
        } else {
            command = new String[]{"/root/hadoop-2.7.2/sbin/zkServer.sh", "start"};
        }
        Process process = Runtime.getRuntime().exec(command);
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                process.getInputStream()));
        String s;
        while ((s = reader.readLine()) != null) {
            if (s.contains("nodemanager")) {
                params.put("yarnStart", String.valueOf(true));
                WebSocketServer.sendInfo(JSONObject.toJSONString(params));
            }
            if (s.contains("secondarynamenode")) {
                params.put("hdfsStart", String.valueOf(true));
                WebSocketServer.sendInfo(JSONObject.toJSONString(params));
            }
            System.out.println("Script output: " + s);
        }
        return new Result(true, 20000, "启动组件成功", null);
    }

    @ApiOperation(value = "停止组件", notes = "停止组件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "", required = true, paramType = "query"),
    })
    @GetMapping(value = "/stop")
    public Object stop(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HashMap<String, Object> params = new HashMap<>(Constant.HASH_MAP_SIZE);

        params.put("type", request.getParameter("type"));
        String[] command;
        if (params.get("type").equals("yarn")) {
            command = new String[]{"/root/hadoop-2.7.2/sbin/stop-yarn.sh"};
        } else if (params.get("type").equals("hdfs")) {
            command = new String[]{"/root/hadoop-2.7.2/sbin/stop-dfs.sh"};
        } else {
            command = new String[]{"/root/hadoop-2.7.2/sbin/zkServer.sh", "stop"};
        }
        Process process = Runtime.getRuntime().exec(command);
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                process.getInputStream()));
        String s;
        while ((s = reader.readLine()) != null) {
            if (s.contains("proxyserver")) {
                params.put("yarnStop", String.valueOf(true));
                WebSocketServer.sendInfo(JSONObject.toJSONString(params));
            }
            if (s.contains("secondarynamenode")) {
                params.put("hdfsStop", String.valueOf(true));
                WebSocketServer.sendInfo(JSONObject.toJSONString(params));
            }
            System.out.println("Script output: " + s);
        }
        return new Result(true, 20000, "停止组件成功", null);
    }

    @ApiOperation(value = "获取组件状态", notes = "获取组件状态")
    @ApiImplicitParams({})
    @GetMapping(value = "/status")
    public Object getStatus(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Process process = Runtime.getRuntime().exec("jps");
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                process.getInputStream()));
        String s;
        HashMap<Object, Object> params = new HashMap<>(Constant.HASH_MAP_SIZE);
        while ((s = reader.readLine()) != null) {
            if (s.contains("QuorumPeerMain")) {
                params.put("zk", String.valueOf(true));
                WebSocketServer.sendInfo(JSONObject.toJSONString(params));
            }
            if (s.contains("DataNode")) {
                params.put("hdfs", String.valueOf(true));
                WebSocketServer.sendInfo(JSONObject.toJSONString(params));
            }
            if (s.contains("ResourceManager")) {
                params.put("yarn", String.valueOf(true));
                WebSocketServer.sendInfo(JSONObject.toJSONString(params));
            }
            System.out.println("Script output: " + s);
        }

        return new Result(true, 20000, "获取组件状态成功", null);
    }


    @ApiOperation(value = "获取xml文件", notes = "获取xml文件")
    @GetMapping(value = "/getXmlFile")
    public Object getXmlFile(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String filePath = "src/main/resources/file/hdfs-site.xml";
        Document document = XmlUtil.getDocument(filePath);
        String docXmlText = document.asXML();//输出xml字符串
        return new Result(true, 20000, "获取hdfs-site.xml成功", docXmlText);
    }


    @ApiOperation(value = "修改xml文件", notes = "修改xml文件")
    @ResponseBody()
    @PostMapping(value = "/putXmlFile")
    public Object putXmlFile(@RequestBody XmlDO body, HttpServletResponse response) throws Exception {
        Document document = DocumentHelper.parseText(body.getData());//字符串转xml
        String filePath = "src/main/resources/file/hdfs-site.xml";
        XmlUtil.coverElement(filePath, document);
        return new Result(true, 20000, "修改hdfs-site.xml成功", body.getData());
    }

    @ApiOperation(value = "获取csv文件", notes = "获取csv文件")
    @GetMapping(value = "/getCsvFile")
    public Object getCsvFile(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String newFile = "src/main/resources/test.csv";
        List list = CsvUtil.readCsv(newFile);
        return new Result(true, 20000, "获取csv成功", list);
    }

    @ApiOperation(value = "修改csv文件", notes = "修改csv文件")
    @ResponseBody()
    @PostMapping(value = "/putCsvFile")
    public Object putCsvFile(@RequestBody CsvDO body, HttpServletResponse response) throws Exception {
        String newFile = "src/main/resources/test.csv";
        CsvUtil.writeCsv(newFile, body.getData());
        return new Result(true, 20000, "修改hdfs-site.xml成功", "SUCCESS");
    }

    @ApiOperation(value = "操作系统级情况查询", notes = "操作系统级情况查询")
    @GetMapping(value = "/getSystemInfo")
    public Object getCpuInfo(HttpServletRequest request, HttpServletResponse response) throws Exception {
//        OperatingSystemMXBean mem = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
//        double processCpuLoad = mem.getProcessCpuLoad();
//        double systemCpuLoad = mem.getSystemCpuLoad();
//        long processCpuTime = mem.getProcessCpuTime();
//        SystemInfoDO res = new SystemInfoDO();
//        res.setProcessCpuLoad(processCpuLoad);//返回Java虚拟机进程的“最近的cpu用法”。
//        res.setSystemCpuLoad(systemCpuLoad);//	返回整个系统的“最近的cpu使用率”。
//        res.setProcessCpuTime(processCpuTime);//返回运行Java虚拟机的进程使用的CPU时间（以纳秒为单位）。
//
//        int byteToMb = 1024 * 1024;
//        OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
//        String os = System.getProperty("os.name");
//        long physicalFree = osmxb.getFreePhysicalMemorySize() / byteToMb;
//        long physicalTotal = osmxb.getTotalPhysicalMemorySize() / byteToMb;
//        long physicalUse = physicalTotal - physicalFree;
//        res.setOs(os);//操作系统的版本
//        res.setPhysicalFree(physicalFree);//操作系统物理内存已用的空间
//        res.setPhysicalTotal(physicalTotal);//操作系统物理内存的空闲空间
//        res.setPhysicalUse(physicalUse);//操作系统总物理内存
        SystemInfoDO res = new SystemInfoDO();
        printlnCpuInfo(res);
        MemInfo(res);
        DiskInfo(res);
        NetInfo(res);
        setSysInfo(res);
        return new Result(true, 20000, "获取CPU使用率成功", res);
    }

    private static void printlnCpuInfo(SystemInfoDO res) throws InterruptedException {
        //System.out.println("----------------cpu信息----------------");
        SystemInfo systemInfo = new SystemInfo();
        CentralProcessor processor = systemInfo.getHardware().getProcessor();
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        // 睡眠1s
        TimeUnit.SECONDS.sleep(1);
        long[] ticks = processor.getSystemCpuLoadTicks();
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
        long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
        int cpuCount = processor.getLogicalProcessorCount();
        double systemCpuLoad = cSys * 1.0 / totalCpu;
        double userCpuLoad = user * 1.0 / totalCpu;
        double iowaitCpuLoad = iowait * 1.0 / totalCpu;
        double idleCpuLoad = 1.0 - idle * 1.0 / totalCpu;
        res.setCpuCount(cpuCount);
        res.setSystemCpuLoad(systemCpuLoad);
        res.setUserCpuLoad(userCpuLoad);
        res.setIowaitCpuLoad(iowaitCpuLoad);
        res.setIdleCpuLoad(idleCpuLoad);
        System.out.println("----------------cpu信息----------------");
        System.out.println("cpu核数:" + processor.getLogicalProcessorCount());
        System.out.println("cpu系统使用率:" + new DecimalFormat("#.##%").format(cSys * 1.0 / totalCpu));
        System.out.println("cpu用户使用率:" + new DecimalFormat("#.##%").format(user * 1.0 / totalCpu));
        System.out.println("cpu当前等待率:" + new DecimalFormat("#.##%").format(iowait * 1.0 / totalCpu));
        System.out.println("cpu当前使用率:" + new DecimalFormat("#.##%").format(1.0 - (idle * 1.0 / totalCpu)));
    }

    public static void NetInfo(SystemInfoDO res) {
        System.out.println("----------------网络信息----------------");
        SystemInfo si = new SystemInfo();
        HardwareAbstractionLayer hal = si.getHardware();
        List<oshi.hardware.NetworkIF> networkIFs = hal.getNetworkIFs();
        for (NetworkIF net : networkIFs) {
            System.out.format(" 网络设备名: %s (%s)%n", net.getName(), net.getDisplayName());
            System.out.format("   MAC地址: %s %n", net.getMacaddr());
            System.out.format("   MTU: %s, Speed: %s %n", net.getMTU(), FormatUtil.formatValue(net.getSpeed(), "bps"));
            System.out.format("   IPv4: %s %n", Arrays.toString(net.getIPv4addr()));
            System.out.format("   IPv6: %s %n", Arrays.toString(net.getIPv6addr()));
            boolean hasData = net.getBytesRecv() > 0 || net.getBytesSent() > 0 || net.getPacketsRecv() > 0
                    || net.getPacketsSent() > 0;
            System.out.format("   流量：已接收 %s/%s%s; 已传输 %s/%s%s %n",
                    hasData ? net.getPacketsRecv() + " 包" : "?",
                    hasData ? FormatUtil.formatBytes(net.getBytesRecv()) + "-" + net.getBytesRecv() : "?",
                    hasData ? " (" + net.getInErrors() + " err)" : "",
                    hasData ? net.getPacketsSent() + " 包" : "?",
                    hasData ? FormatUtil.formatBytes(net.getBytesSent()) + "-" + net.getBytesSent() : "?",
                    hasData ? " (" + net.getOutErrors() + " err)" : "");
        }
    }

    public static void MemInfo(SystemInfoDO res) {
        System.out.println("----------------主机内存信息----------------");
        SystemInfo systemInfo = new SystemInfo();
        GlobalMemory memory = systemInfo.getHardware().getMemory();
        //总内存
        long totalByte = memory.getTotal();
        //剩余
        long availableByte = memory.getAvailable();
        res.setMemoryTotal(totalByte);//操作系统总物理内存
        res.setMemoryFree(availableByte);//操作系统物理剩余内存
        res.setMemoryUse(totalByte - availableByte);//操作系统物理内存使用
        System.out.println("总内存 = " + FormatUtil.formatBytes(totalByte));
        System.out.println("使用" + FormatUtil.formatBytes(totalByte - availableByte));
        System.out.println("剩余内存 = " + FormatUtil.formatBytes(availableByte));
        System.out.println("使用率：" + new DecimalFormat("#.##%").format((totalByte - availableByte) * 1.0 / totalByte));
    }

    public static void DiskInfo(SystemInfoDO res) {
        System.out.println("---------------主机硬盘信息----------------");
        File[] disks = File.listRoots();
        long disksTotal = 0;
        long disksUse = 0;
        long disksFree = 0;
        for (File file : disks) {
            disksTotal += file.getTotalSpace();
            disksUse += file.getUsableSpace();
            disksFree += file.getFreeSpace();
            System.out.print(file.getPath() + "    ");
            System.out.print("空闲未使用 = " + FormatUtil.formatBytes(file.getFreeSpace()) + "    ");// 空闲空间
            System.out.print("已经使用 = " + FormatUtil.formatBytes(file.getUsableSpace()) + "    ");// 已经使用
            System.out.print("总容量 = " + FormatUtil.formatBytes(file.getTotalSpace()) + "    ");// 总空间
            System.out.println();
        }
        res.setDisksTotal(disksTotal);
        res.setDisksUse(disksUse);
        res.setDisksFree(disksFree);
    }

    public static void setSysInfo(SystemInfoDO res) {
        System.out.println("----------------操作系统信息----------------");
        Properties props = System.getProperties();
        //系统名称
        String osName = props.getProperty("os.name");
        //架构名称
        String osArch = props.getProperty("os.arch");
        res.setOsName(osName);//操作系统的版本
        res.setOsArch(osArch);//系统架构
        System.out.println("操作系统名 = " + osName);
        System.out.println("系统架构 = " + osArch);
    }
}
